package com.cskaoyan.yesterday.edition2;
public class Work {

    /**

     *

     * 既然是两个线程交替打印，那就是一个线程打印奇数，一个线程打印偶数

     * 奇数线程打印奇数，然后让被打印数字增1

     * 偶数线程打印偶数，然后让被打印数字增1

     * 知道打印到题目中数字的上界99

     */

    public static void main(String[] args) {

        //创建PrintNumber对象，该对象记录了被打印数字，同时，创建该对象时，指定打印数字的上界
        PrintNumber printNumber = new PrintNumber(99);
        OddTask oddTask = new OddTask(printNumber);
        EvenTask evenTask = new EvenTask(printNumber);

        new Thread(evenTask, "线程1").start();
        new Thread(oddTask, "线程2").start();

    }



}



/*

   定义一个类，封装被打印的数字

*/

class PrintNumber {

    private int i = 0;

    //指定被打印数字的上线，在题目中upBound的取值为99，只要打印到99即可

    private int upBound;

    public PrintNumber(int upBound) {

        this.upBound = upBound;

    }



 /*

     让被打印数字增1

  */

    public void add() {

        i++;

    }



 /*

     获取打印数字的上界

  */

    public int getUpBound() {

        return upBound;

    }



 /*

     获取被打印数字当前的值

  */

    public int value() {

        return i;

    }

}





/*

     打印奇数，和偶数线程的公共父类，打印的主要逻辑都在该类中

     子类只实现，具体的打印条件的判断即可，可以很大程度的复用代码

*/

abstract class PrintTask implements Runnable {



 /*

      奇数偶数线程共同打印的对象，该对象中包含被打印数字的值

  */

    protected PrintNumber number;



    public PrintTask(PrintNumber number) {

        this.number = number;

    }



    @Override

    public void run() {

        //如果还没打印到最大值，就接着循环打印
        while (number.value() <= number.getUpBound()) {
            synchronized (number) {

                if (number.value() > number.getUpBound() ) {

                    //如果超出打印数字的上界，就退出循环不打印

                    break;

                }



                if (!shouldPrint()) {

                    //如果不满足打印条件，当前线程就不打印

                    try {

                        number.wait();

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }



                } else {

                    // 满足当前线程的打印条件



                    //打印数字的值
                    System.out.println(Thread.currentThread().getName() + " i = " + number.value());

                    //使被打印数字的值增1
                    number.add();

                    if (number.value() > number.getUpBound()) {
                        //被打印的数字的值，已经超过了了上界，即打印完了
                        System.out.println("打印完毕");
                    }

                    // 通知其他等待的打印线程，继续打印

                    number.notifyAll();

                }

            }



        }

    }

    // 该方法由子类实现，判断当前线程是否该打印数字i的值

    protected abstract boolean shouldPrint();

}



/*

   打印奇数

*/

class OddTask extends PrintTask {



    public OddTask(PrintNumber number) {

        super(number);

    }



 /*

     打印奇数的线程，当number对象中，i的值为奇数时才打印

  */

    @Override
    protected boolean shouldPrint() {

        return number.value() % 2 != 0;

    }

}



/*

   打印偶数

*/

class EvenTask extends PrintTask {

    public EvenTask(PrintNumber number) {

        super(number);

    }



 /*

    打印偶数的线程，当number对象中，i的值为偶数时才打印

 */

    @Override
    protected boolean shouldPrint() {
        return number.value() % 2 == 0;
    }

}